﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data.OleDb;
using MongoDB.Bson;
using MongoDB.Bson.Serialization.Attributes;
using MongoDB.Driver;
using lo = sqCore.sqLogger;



namespace sqCore
{
    /* Docs:
     * Summary
        * DB object for SqlA Server.
        * Allows connection to the DB.
        * Can hadle with all SQL relational dbs, and MongoDB.
     * Variables:
        * Id - Unique Id for the DB.
        * DBType - The Type of the DB.
        * Name - Name for the DB (Should be unique).
        * Host - The DB host path (IP/HostName/localhost).
        * Port - Port for the DB's server. If not set - will be defualt port.
        * UserName - UserName for DB connection.
        * Password - Password for DB connection.
     */
    public class sqDB    
    {
        //[BsonIgnoreIfDefault]
        public ObjectId Id { get; set; }        
        public string DBType { get; set; }
        public string Name { get; set; }
        public string Host { get; set; }
        public string ServiceName { get; set; }
        public string Port { get; set; }
        public string UserName { get; set; }
        public string Password { get; set; }

        /* Docs:
         * Summary: Initialize the Task.
         */
        public sqDB(string Name, string Host, string ServiceName, string DBType = "Oracle", string Port = "0", string UserName = "Admin", string Password = "Admin")
        {
            this.Name = Name;
            this.Host = Host;
            this.ServiceName = ServiceName;
            this.Port = Port;
            this.UserName = UserName;
            this.Password = Password;
            this.DBType=DBType;            
        }
        
        /* Docs:
        * Summary: Get a dictionary with all DB params.
        */
        public Dictionary<string,string> getDBParams()
        {
            return new Dictionary<string, string>() {  { "DBType", this.DBType.ToString() }, { "Name", this.Name }, { "Host", this.Host }, { "ServiceName", this.ServiceName }, { "Port", this.Port }, { "UserName", this.UserName }, { "Password", this.Password } };
        }

        /* Docs:
        * Summary: Format params to Oracle connection path
        */
        public string getOracleDataSourcePath()
        {
            return "(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST="+this.Host+")(PORT="+this.Port+"))(CONNECT_DATA=(SERVICE_NAME="+this.ServiceName+"))); User Id="+this.UserName+";Password="+this.Password+";";
        }

        /* Docs:
        * Summary: Retuens open connection to the Oracle DB.
        * Variables:
            * conn - Connection to Oracle DB
        */
        public OleDbConnection makeOracleConnection()
        {
            if (this.Port == "0")
                this.Port = "1521";
            OleDbConnection conn = new OleDbConnection("Provider=OraOLEDB.Oracle; Data Source =" + this.getOracleDataSourcePath());
            lo.writeLog(LogMessage: "Oracle DB connection has been made.", Param: this.Name);
            return conn;
        }

        /* Docs:
        * Summary: Retuens connection to the MSSQL DB.
        * Variables:
            * conn - Connection to Oracle DB
        */
        public OleDbConnection makeMSSQLConnection()
        {
            if (this.Port == "0")
                this.Port = "1433";
            if (this.Host.ToLower() == "localhost" || this.Host == "127.0.0.1")
                this.Host = ".";
            OleDbConnection conn = new OleDbConnection("Provider=SQLOLEDB; Server=" + this.Host + ";Database=" + this.ServiceName + ";User Id=" + this.UserName + "; Password=" + this.Password);
            lo.writeLog(LogMessage: "MSSQL DB connection has been made.", Param: this.Name);
            return conn;
        }
        
        /* Docs:
        * Summary: Retuens connection to the Mongo DB.
        * Variables:
            * conn - Connection to Oracle DB
        */
        public MongoDatabase makeMongoConnection()
        {
            if (this.Port == "0")
                this.Port = "27017";
            if (this.Host == "." || this.Host == "127.0.0.1")
                this.Host = "localhost";
            MongoClient client = new MongoClient(@"mongodb://" + this.Host + @":" + this.Port+@"/"+this.ServiceName);
            
            Console.WriteLine(@"mongodb://" + this.Host + @":" + this.Port + @"/" + this.ServiceName);
            MongoServer server = client.GetServer();            
            if (!server.DatabaseExists(ServiceName))
                throw new System.Exception();
            MongoDatabase conn = server.GetDatabase(this.ServiceName);
            return conn;
        }

        /* Docs:
        * Summary: Check which if Oracle or MSSQL and returns the currect connection.
        */
        public OleDbConnection connect()
        {
            sqHelpper.DBType DBType = sqHelpper.formatToDBType(this.DBType);
            if (DBType == sqHelpper.DBType.Oracle)
                return makeOracleConnection();
            else if (DBType == sqHelpper.DBType.MSSQL)
                return makeMSSQLConnection();
            else
                return new OleDbConnection();
        }
        
        /* Docs:
        * Summary: Try to connect to the db, and return if success.
        */
        public bool checkConnection()
        {
            sqHelpper.DBType DBType = sqHelpper.formatToDBType(this.DBType);
            try
            {
                if (DBType == sqHelpper.DBType.Oracle)
                {
                    OleDbConnection conn = makeOracleConnection();
                    conn.Open();
                    conn.Close();
                }
                else if (DBType == sqHelpper.DBType.MSSQL)
                {
                    OleDbConnection conn = makeMSSQLConnection();
                    conn.Open();
                    conn.Close();
                }
                else if (DBType == sqHelpper.DBType.Mongo)
                {
                    MongoDatabase conn = makeMongoConnection();
                }
                else
                    return false;
                return true;
            }
            catch { return false; }                       
        }

        /* Docs:
        * Summary: Check if two sqDB is equals, using the DB's ids.
        */
        public override bool Equals(object t)
        {
            if (t.GetType() == typeof(sqDB))
                return (Id == ((sqDB)t).Id);
            return false;
        }

    }
}


